package com.suxin.shiro.jwt.realm;

import com.suxin.shiro.jwt.listener.UserAuthenticationListener;
import com.suxin.shiro.jwt.token.JwtToken;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationListener;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.realm.Realm;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Tang
 * @classname UserModularRealmAuthenticator
 * @description [  ]
 * @date 2021/3/21 22:24
 */
public class UserModularRealmAuthenticator extends ModularRealmAuthenticator {

    public UserModularRealmAuthenticator() {
        super();
        Collection<AuthenticationListener> listeners = new ArrayList<>(10);
        listeners.add(new UserAuthenticationListener());
        this.setAuthenticationListeners(listeners);
    }

    /**
     * 这个方法，调用login是会执行这个选择合适的realm
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("UserModularRealmAuthenticator:method doAuthenticate() 执行！");
        assertRealmsConfigured();
        Collection<Realm> realms = getRealms();
        // 分发realms
        if (authenticationToken instanceof JwtToken) {
            JwtToken jwtToken = (JwtToken) authenticationToken;
            // 获取jwt的realm
            List<Realm> jwtRealms = realms.stream().filter((item) -> item.getName().contains("JwtRealm")).collect(Collectors.toList());
            return doSingleRealmAuthentication(jwtRealms.get(0), jwtToken);
        }
        // 其他的
        return doMultiRealmAuthentication(
                realms.stream().filter(
                        (item) -> !item.getName().contains("JwtRealm")).collect(Collectors.toSet()
                ),
                authenticationToken
        );
    }

    @Override
    protected void notifyFailure(AuthenticationToken token, AuthenticationException ae) {
        super.notifyFailure(token, ae);
    }
}